﻿/**
 * nPnP - neither Perl not PHP
 *
 * Copyright (C) 2009 Christian Moeller
 *
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the 
 * Free Software Foundation; either version 3 of the License, or (at your option) 
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; 
 * if not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FParser.Parser;
using System.IO;
using FParser.Visualization;
using System.Collections;
using FParser.Tools;

namespace FParser
{
    class Program
    {
        /// <summary>
        /// Thats the main application! Everything starts from HERE ;-)
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Dictionary<string, string> options = new Dictionary<string, string>();
            string file;

            // test if we have arguments, if not, throw an error
            if (args.Length > 0)
            {
                // get the last argument and propose it as file name
                file = args[args.Length - 1];

                // parse all arguments and put them to the options dictionary
                for (int i = 0; i < args.Length; ++i)
                {
                    if (args[i].Contains('='))
                    {
                        string[] optionPair = args[i].Split('=');
                        options.Add(optionPair[0], optionPair[1]);
                    }
                    else
                        options.Add(args[i], null);
                }

                // if either the input file exists, or the option of loading precompiled content is set
                // and this file exists, we start the process
                if (File.Exists(file) || (options.ContainsKey("-i") && File.Exists(options["-i"])))
                {
                    // expression list of main file
                    List<Expression> expressions = new List<Expression>();

                    // if the option -i is set, we load a serialized file 
                    if (options.ContainsKey("-i"))
                    {
                        if (options["-i"] != null)
                            expressions = OpCodeSerialization.DeserializeExpressions(options["-i"]);
                    }
                    else
                    {
                        // else we parse the main input file... 
                        // you should prefer loading precompiled files

                        StreamReader read = new StreamReader(file);
                        string data = read.ReadToEnd();

                        PreCompiler preCompiler = new PreCompiler(data);
                        data = preCompiler.Process();

                        Tokenizer tokenizer = new Tokenizer(data);
                        List<Token> tokens = tokenizer.Tokenize(true);

                        TokenParser parser = new TokenParser(tokens);
                        expressions = parser.Parse();
                    }

                    // if we want to export a dot file, this will be done!
                    if (options.ContainsKey("-dot"))
                    {
                        if (options["-dot"] != null)
                        {
                            DotExporter dExport = new DotExporter(expressions);
                            StreamWriter writer = new StreamWriter(options["-dot"]);
                            writer.Write(dExport.Export());
                            writer.Close();
                        }
                    }

                    // if the output option is set, a serialized data stream of the expression list
                    // is written to the provided file
                    if (options.ContainsKey("-o") && !options.ContainsKey("-i"))
                    {
                        if (options["-o"] != null)
                        {
                            OpCodeSerialization.SerializeExpressions(expressions, options["-o"]);
                            Environment.Exit(0);
                        }
                    }

                    // if nothing else happend, we execute it!
                    Executor.Executor executor = new FParser.Executor.Executor(expressions);
                    executor.Run();

           
                }
                else
                {
                    Console.WriteLine("Error: the file " + args[0] + " cannot be found.");
                }
            }
            else
            {
                Console.WriteLine("Synopsis: FParser.exe [OPTIONS] sourcefile\nOptions:\n\t-o\tCreate precompiled output file.\n\t-i\tLoad precompiled file.\n\t-dot\tCreate dot output graph.");
            }
           
        }
    }
}
